你設計的 API 除了跑的動以外,它安全穩定嗎?
既然 Junoir 跟 Senior 的後端工程師都能寫出可以運作的 API;那公司為什麼要多花錢請一個比較貴的工程師呢?
不僅面試官會問這個問題,你也要時常反問自己:「我憑什麼可以開出更高的薪水?我跟其他的工程師有哪裡不一樣?
」
設計 API 時會考慮哪些點?
回答問題所需具備的知識
衍伸問題
能依照需求規格書寫好 API 只是對後端工程師的基礎要求;但這個 API 考慮的是否周全就看每個工程師的經驗了。
這算是常見面試題
,面試官想從回答中了解你後端的實作經驗與基本功,並判斷你在進入團隊後是否需要花更多時間訓練才能成為有效戰力。
以過去設計的內部管理系統來說,Client 端在登入後會取得 JWT,之後在存取 API 前會用這個 JWT 來驗證是否有存取的權限
;為了避免 Client 端使用不符規範的參數,我會先驗證每個傳入參數的格式
,並撰寫 Unit Test
確保這隻 API 在不同情境下的 Response 都符合期待;再確認 API 的穩定性後,我會去思考還有什麼地方可以優化,讓 Client 端有更好的體驗。
這邊帶讀者瞭解兩種主流驗證機制,大部分的框架都有提供對應的方案供開發人員使用。
很多使用者上線時要面對的效能或是記憶體問題
。
不同 Server 的 Session 共享問題
。
不要為了方便把 JWT 的有效期限設定太長
,不然這個 JWT 洩露出去後,任何人都可以拿它來幹大事。
無論前端驗證做得多完美,後端驗證都是必須存在的
;因為想攻擊系統的人不一定會從前端執行,直接 Call API 嘗試所有可能性的效率快多了;前端驗證可以大幅減少不必要的 Request 產生,後端驗證則是保護資料的最終防線
。
為什麼要了解 Validation Rule?
接下來用情境來介紹幾個常見的 Validation Rule,不同框架的名字可能略有不同,我這邊以 Laravel 的為主。
驗證使用者註冊系統時填寫的參數
此為 Laravel 驗證傳入參數的程式,下方依據參數進行解說。
$validator = Validator::make($request->all(), [
'email' => ['required', 'email', 'string', 'max:255', 'unique:users'],
'name' => ['required', 'string', 'max:50'],
'password' => ['required', 'string', 'max:255', 'min:8', 'regex:/^.*(?=.{8,})(?=.*?[a-zA-Z])(?=.*?[0-9]).*$/', 'confirmed']
]);
required
欄位,同時檢查傳入的字串是否符合 email
格式以及長度 max
是否超過限制,並確認這個 email 並沒有被註冊過 unique
。required
欄位,同時檢查傳入的字串長度 max
是否超過限制。required
欄位,除了檢查傳入的字串長度 max
是否超過限制外,通常會限制最小長度 min
;再嚴謹一點會要求 password 複雜度需包含英數字 regex
,且內容與 password_confirmation 欄位相同 confirmed
。這邊先不討論程式語言和資料庫選擇帶來的影響,專注在共同可行性方案上。
操作資料庫時加入限制條件
就算前端 Request 的參數沒有限制條件(ex:分頁、筆數、種類...),後端也要有意識的設定預設值
,不然當資料量大的時候除了會跑很久浪費效能外,前端也不適合接收/呈現這麼多資訊。
回傳前端的資料盡量是已經計算過的
Client 端使用的機器效能未知,如果把太多的邏輯運算交給前端可能導致不好的使用者體驗;我這邊建議後端最好回傳計算後的資料
,前端負責顯示為主,不過這塊也要看實際的業務量以及情境來 trade-off 。
加入 CDN Cache
如果遇到國外客戶抱怨連線速度很慢,就可以考慮採用 CDN 來解決這個問題;CDN 服務商的做法是將 Server 建置在世界各地,將網站上的靜態內容(圖片、影音、檔案)與動態內容(資料庫查詢)Cache 到 Server,根據訪客的地理位置,從最近的 Server 提供資料
;好處如下:
提升硬體水平
江湖傳言:「效能不夠,機器來湊!」雖然聽起來好像是在開玩笑;但實際業務上如果真的遇到效能瓶頸,許多公司的做法就是先靠硬體讓服務穩定
;服務穩定了,你才有心力去 Refactor 程式。
程式碼的穩定性
,發生錯誤時可以快速找到源頭,因此開發人員可以更大膽的開發。降低相關維運成本
。確保舊版 API 可以正常運行
。確保合併分支的程式正確性
。測試程式邏輯
,建議測試時使用 Mock data,不然可能導致正式環境發生意外。少寫的測試往往上線後就會爆掉
。把所有錯誤情境都做一次模擬
;甚至要模擬 JWT 還在有效期,但實際權限已被移除的邊緣測試
。筆者聽過有些公司在專案正式 Release 時沒有撰寫任何的 Unit Test,直接讓客戶人肉測試,等客戶回報錯誤時再去修復 Bug;嗯...這種公司的離職率通常很高,因為有一堆歷史業障需要修但沒人敢碰。
考點:對於 API 基礎操作的掌握程度
「PUT」是替換
資源,而「PATCH」則是更新部份
資源內容;以使用者舉例,假設他有「姓名、簡介、年齡」這幾個欄位,如果想更新「姓名」的資訊:
考點:確認你寫 API 的習慣是否符合標準
假設今天有一個 users 的 Table。
/api/users
/api/users/{user_id}
/api/users
/api/users/{user_id}
/api/users/{user_id}
考點:確認你對市場技術的認知程度
過去 RESTful API
需要根據需求規格書給每個 API 設計回傳的資料結構
,如果這個 API 在很多頁面被共用就有可能要回傳更多的資訊,但回傳的資訊中有些是只有特定頁面才有需求的,假使拆成多隻 API 也會導致日後維護困難;而 GraphQL
的出現正好解決了這個問題,他能夠由 Client 端來定義 Server 端要回傳的資料結構
,不再回傳冗贅資訊。
補充:用範例了解兩者差異
要查詢圖書館中特定書籍,回傳內容須包含:「作者、書名、出版年」。
GraphQL
Client 端傳送的 query
query {
books (id:12) {
authors {
firstName
lastName
}
title
yearPublished
}
}
Server 端 Response 的 result
{
"data": {
"books": {
"authors": [
{
"firstName": "Lin",
"lastName": "Dean"
}
],
"title": "全端工程師生存筆記",
"yearPublished": "2022"
}
}
}
RESTful API
Client 端的 Request
需要拆成GET api/books/12
、GET api/authors/12
來分別取得書籍、作者資訊。
Server 端 Response 的 resultGET api/books/12
{
"title" : "全端工程師生存筆記",
"authorID": 12,
"yearPublished" : 2022,
"page": 168,
"tags": ["履歷"、"面試"、"職場"]
}
GET api/authors/12
{
"firstName": "Lin",
"lastName": "Dean"
}
在上面的範例中,RESTful API 需要兩個 Request 才能取得完整資料,如果想用一個 Request 取得完整資料就要重新建立一支 API;比較起來GraphQL 對前端工程師來說是更好使用的工具
;不過轉換與建立的成本較 RESTful API 高,如果想嘗試 GraphQL 帶來的效益,可以考慮漸進式的遷移。
感謝大家的閱讀,如果喜歡我的文章可以訂閱
接收通知;如果有幫助到你,按Like
可以讓我更有寫文的動力,我們明天見~
我在 Medium 平台 也分享了許多技術文章
❝ 主題涵蓋「MIS & DEVOPS、資料庫、前端、後端、MICROSFT 365、GOOGLE 雲端應用、自我修煉」希望可以幫助遇到相同問題、想自我成長的人。❞
在許多人的幫助下,本系列文章已成功出版,除了添加新的篇章,更完善了每個案例的應對進退;如果對現在的職涯感到迷茫,也許這本書能帶給你不一樣的觀點~